package org.vsg.stock.job;


import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.vsg.common.exceptions.service.ServiceException;
import org.vsg.stock.basic.StockHelper;
import org.vsg.stock.basic.domain.StockCategory;
import org.vsg.stock.basic.domain.StockDailyLine;
import org.vsg.stock.basic.persistence.StockCategoryDao;
import org.vsg.stock.extension.service.StockAnalysisService;
import org.vsg.stock.extension.vo.LinkageStock;
import org.vsg.stock.extension.vo.LinkageStockGroup;

/**
 * @author bill vison
 *
 */
public class StockCategoryBuildIndexJob implements Job {

	private static final Logger logger = LoggerFactory.getLogger(StockCategoryBuildIndexJob.class);	
	
	private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");	
	
	/* (non-Javadoc)
	 * @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
	 */
	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		// TODO Auto-generated method stub
		JobDataMap dm = context.getMergedJobDataMap();
		Properties config = (Properties)(dm.get( "APPLICATION_SYSTEM_CONFIGRATION" ));
		
		// --- reade the spring context ---
		String[] configContextFiles = {
				"classpath*:spring/**/configurationContext-quartz.xml",
				"classpath*:spring/**/applicationContext.xml",
				"classpath*:spring/**/dataAccessContext.xml"
		};

		
		GenericApplicationContext ctx = new GenericApplicationContext();
		ctx.registerBeanDefinition( "propertyConfigurer" , dynamicBeanDefined(config)  );
		XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(ctx);
		xmlReader.loadBeanDefinitions(configContextFiles);
	
		ctx.refresh();
		
		// ---- get the context bean ---
		File linkageDir = new File(config.getProperty("stock.linkage.dir"));
		
		if (logger.isDebugEnabled() ) {
			logger.debug( "log in directory : " + linkageDir.getAbsolutePath() );
		}
		
		workJob(ctx,linkageDir);
		
	}
	
	private BeanDefinition dynamicBeanDefined(Properties props) {
		MutablePropertyValues mpv = new MutablePropertyValues();
		mpv.addPropertyValue("properties", props);
		RootBeanDefinition ged = new RootBeanDefinition(PropertyPlaceholderConfigurer.class , mpv);
		return ged;
	}
	
	
	private void workJob(ApplicationContext ctx , File dir) {
		StockAnalysisService stkAnalyService = (StockAnalysisService)ctx.getBean("stockAnalysisService");
		StockCategoryDao stockCategoryDao = (StockCategoryDao)ctx.getBean("stockCategoryDao");
		
		// get the date period 
		Calendar tmpCale = Calendar.getInstance();
		Date endDate = tmpCale.getTime();
		
		// --- before a week --
		tmpCale.add(Calendar.DATE, -7 );
		Date startDate = tmpCale.getTime();		
		
		List<LinkageStockGroup> LinkageStockGroupList = null;
		Map<String, StockCategory> cateMap = new HashMap<String,StockCategory>();
		try {
			LinkageStockGroupList = stkAnalyService.findStockGroupListInPeriod(startDate, endDate, 3);
			
			LinkageStockGroup linkageStkGroup = null;
			StringBuffer builder = new StringBuffer();
			StockCategory stockCategory = null;
			List<LinkageStock> linkageStkList = null;
			LinkageStock linkageStock = null;
			StringBuffer assoStocks = null;
			File file = null;
			Date tradingDate = null;
			StockHelper helper = StockHelper.getInstance();
			for (Iterator<LinkageStockGroup> linkageStkGroupIter = LinkageStockGroupList.iterator() ; linkageStkGroupIter.hasNext(); ) {
				linkageStkGroup = linkageStkGroupIter.next();
				
				tradingDate = linkageStkGroup.getDate();
				// --- build the file ---
				file = new File(dir, sdf.format( tradingDate )+".txt");

				if (!helper.isTradingDate( tradingDate ) || file.exists()) {
					continue;
				}
				
				OutputStream os = null;
				try {
					
					linkageStkList = linkageStkGroup.getLinkageStockList();
					
					for (Iterator<LinkageStock> linkageStkIter = linkageStkList.iterator() ; linkageStkIter.hasNext(); ) {
						linkageStock = linkageStkIter.next();
						stockCategory = linkageStock.getStockCategory();
						
						builder.append(stockCategory.getId()).append(",");
						builder.append(stockCategory.getDescription()).append(",");
						builder.append(linkageStock.getCount()).append(",");					
						builder.append(linkageStock.getAvgRatio()).append(",");					

						String type = stockCategory.getType();
						
						if (StockCategory.SAME_STOCKHOLDER.equalsIgnoreCase(type)) {
							builder.append(StockCategory.SAME_STOCKHOLDER);
						}
						else if (StockCategory.CONCEPT.equalsIgnoreCase(type)) {
							builder.append(StockCategory.CONCEPT);
						}
						else if (StockCategory.OTHERS.equalsIgnoreCase(type)) {
							builder.append(StockCategory.OTHERS);					
						}				
						else if (StockCategory.PLATE.equalsIgnoreCase(type)) {
							builder.append(StockCategory.PLATE);					
						}				
						else if (StockCategory.STANDARD_TRADES.equalsIgnoreCase(type)) {
							builder.append(StockCategory.STANDARD_TRADES);					
						}				
						else if (StockCategory.TRADES.equalsIgnoreCase(type)) {
							builder.append(StockCategory.TRADES);					
						}				
						else if (StockCategory.ZONE.equalsIgnoreCase(type)) {
							builder.append(StockCategory.ZONE);					
						}
						
						assoStocks = new StringBuffer();
						
						List<StockDailyLine> assoList = linkageStock.getAssoStocks();
						for (Iterator<StockDailyLine> assoListIter = assoList.iterator() ; assoListIter.hasNext();) {
							assoStocks.append( assoListIter.next().getStockCode() );
							
							if (assoListIter.hasNext()) {
								assoStocks.append("|");
							}
						}
						builder.append(",").append( assoStocks );
						
						
						if (linkageStkIter.hasNext()) {
							builder.append("\n");
						}
						
					}
					
					os = new BufferedOutputStream(new FileOutputStream(file));
					
					IOUtils.write( builder, os , "UTF-8");

					// --- clear all data ---
					builder.delete(0, builder.length());
				
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					if (os != null) {
						try {
							os.close();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}
				

				

			}
		
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
			
	}

}
